import requests
import json
from requests.auth import HTTPBasicAuth
from configparser import ConfigParser
from datetime import datetime, timezone

class Config:
    def __init__(self, config_path='config.ini'):
        self.config = ConfigParser()
        self.config.read(config_path)

    def get_section(self, section):
        if self.config.has_section(section):
            return {k: v for k, v in self.config.items(section)}
        raise Exception(f"Section {section} not found in the configuration file.")

class ZONTClient:
    def __init__(self, api_settings):
        self.api_url = api_settings['api_url']
        self.developer_email = api_settings['developer_email']
        self.app_name = api_settings['app_name']
        self.username = api_settings['username']
        self.password = api_settings['password']
        self.token = None
        self.headers = {
            'X-ZONT-Client': api_settings['developer_email'],
            'Content-Type': 'application/json'
        }

    def authenticate(self):
        """Авторизация и получение токена."""
        url = f"{self.api_url}/get_authtoken"
        auth_response = requests.post(url, auth=HTTPBasicAuth(self.username, self.password), headers=self.headers, json={"client_name": self.app_name})
        if auth_response.status_code == 200:
            self.token = auth_response.json().get('token')
            self.headers['X-ZONT-Token'] = self.token
            return True
        return False

    def make_api_request(self, endpoint, method='GET', data=None, is_binary=False):
        """Выполнение API запроса (GET или POST) и обработка ответа."""
        url = f"{self.api_url}/{endpoint}"
        try:
            if method == 'GET':
                response = requests.get(url, headers=self.headers)
            else:
                response = requests.post(url, json=data, headers=self.headers)
            response.raise_for_status()
            
            if is_binary:
                return response.content
            else:
                return response.json()
        except requests.exceptions.RequestException as e:
            print(e)
            return None
    
    def get_devices_list(self,load_io=True):
        """Получение списка всех устройств пользователя."""
        endpoint = "devices"
        data = {"load_io": load_io}
        response = self.make_api_request(endpoint, method='POST', data=data)
        return response

class Device:
    def __init__(self, client, device_id):
        self.client = client
        self.device_id = device_id

    def get_info(self, key=None):
        """
        Получение информации об устройстве.
        Если ключ не указан, возвращает всю информацию об устройстве.
        Если ключ указан, возвращает значение для данного ключа.
        """
        devices_response = self.client.get_devices_list()
        if devices_response and 'devices' in devices_response:
            for device in devices_response['devices']:
                if str(device['id']) == str(self.device_id):
                    if key and key in device:
                        return device[key]
                    return device
            print(f"Устройство с ID {self.device_id} не найдено.")
        else:
            print("Не удалось получить список устройств.")
        return None
    
    def update(self, data):
        """Обновление настроек устройства."""
        return self.client.make_api_request("update_device", method='POST', data={"device_id": self.device_id, **data})

    def set_mode_temperature(self, temperature=20, target_name="Выходные"):
        """Установка температуры для заданного режима."""
        thermostat_ext_modes_config = self.get_info('thermostat_ext_modes_config')
        if not thermostat_ext_modes_config:
            print("Конфигурация термостата не найдена.")
            return None

        # Поиск режима и изменение температуры
        for mode, config in thermostat_ext_modes_config.items():
            if config.get("name") == target_name and "zone_temp" in config:
                config["zone_temp"]["1"] = temperature
                break
        else:
            print(f"Режим '{target_name}' не найден.")
            return None

        response = self.update({"thermostat_ext_modes_config": thermostat_ext_modes_config})
       
        if response and response.get('ok'):
            print(f"Температура для режима '{target_name}' установлена на {temperature}°C.")
        else:
            print("Ошибка при изменении температуры.")
        return response    

    def gvs_setup(self, mode):
        """
        Включение/выключение ГВС на котле.
        :param mode: 0 для выключения ГВС, не 0 для включения.
        """
        data = {
            'device_id': self.device_id,
            'ot_config': ['ch']
        }

        if mode != 0:
            data['ot_config'].append('dhw')

        response = self.client.make_api_request("update_device", method='POST', data=data)
        
        if response and response.get('ok'):
            action = "выключен" if mode == 0 else "включен"
            print(f"Режим ГВС успешно {action}.")
        else:
            print("Ошибка при изменении режима ГВС.")
        return response
    
    @staticmethod
    def get_unix_time(date_str):
        """Конвертирует дату в формате "%d.%m.%Y" в Unix time."""
        dt = datetime.strptime(date_str, "%d.%m.%Y")
        dt = dt.replace(tzinfo=timezone.utc)
        return int(dt.timestamp())

    def get_archive(self, start_date, end_date, split_by='days'):
        """
        Запрос на создание архива с данными устройства и его скачивание.
        """

        mintime = self.get_unix_time(start_date)
        maxtime = self.get_unix_time(end_date)

        # Создание архива
        endpoint = "generate_archive"
        data = {
            'device_id': self.device_id,
            'mintime': mintime,
            'maxtime': maxtime,
            'split_by': split_by
        }
        response = self.client.make_api_request(endpoint, method='POST', data=data)
        if not response or 'archive_id' not in response:
            print("Не удалось создать архив.")
            return False

        archive_id = response['archive_id']
        
        archive_content = self.client.make_api_request(f"download_generated_archive?archive_id={archive_id}", is_binary=True)
        
        if archive_content:
            timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
            archive_path = f'archive_{timestamp}.zip'
            with open(archive_path, 'wb') as f:
                f.write(archive_content)
            print(f"Архив успешно скачан и сохранен как {archive_path}.")
            return True
        else:
            print("Ошибка при скачивании архива.")
            return False

if __name__ == "__main__":
    config_path = 'config.ini'
    config = Config(config_path)
    api_settings = config.get_section('API_ZONT')

    # Инициализация клиента API с использованием данных из конфига
    client = ZONTClient(api_settings)
    if client.authenticate():
        print("Успешная аутентификация.")
        # Работа с устройством
        device = Device(client, api_settings['device_id'])
        device_info = device.get_info('thermostat_ext_modes_config')
        print(json.dumps(device_info, ensure_ascii=False, indent=2))  # Вывод информации об устройстве
        # Установка температуры
        device.set_mode_temperature(15, "Выходные")
        # Выключение ГВС
        device.gvs_setup(0)
        # Скачивание архива
        #device.get_archive(start_date="01.04.2024", end_date="02.04.2024")
    else:
        print("Ошибка аутентификации.")
